#include <athread.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "am_assert.h"
#include "MemPool.h"
#include "aceMesh_utils.h"

#include "slave.h"
// #include "utils/acelog.h"
// extern unsigned long buil_prof[N_BUILD_PROF];
__thread_local volatile unsigned long get_reply;

extern struct MemPool slave_pool[64];
__thread_local struct MemPool slave_pool_ldm;

struct block *slave_mempool_allocblock(struct MemPool slave_pool)  // init in master
{
    printf("error:从核调用了malloc\n"); 
    // assert(0);
#ifdef TARG_SW5
    struct block *myblock = (struct block *)malloc(sizeof(struct block));
    myblock->data = malloc(UNITSIZE);
#elif TARG_SW9
    struct block *myblock = (struct block *)libc_uncached_aligned_malloc(sizeof(struct block));
    myblock->data = (void *)libc_uncached_aligned_malloc(UNITSIZE);
    printf("libc_uncached_aligned_malloc\n");
// #ifdef ACEMESH_SCHEDULER_PROFILING
//     if(my_mpi_rank<=0)
//         printf("my_block_addr=%p, myblock_data_addr=%p\n",myblock,myblock->data);
// #endif
#endif
//#ifdef ACEMESH_SCHEDULER_PROFILING
  //  mempool_alloc_block_num++;
//#endif

    myblock->next = NULL;
    return myblock;
}
// void slave_InitPool(int _myid)  // use _MYID?
// {
//     // alog_debug("InitPool");
//     slave_pool[_myid].EndBlock = NULL;
//     slave_pool[_myid].AllocatedMemBlock = NULL;
//     slave_pool[_myid].FreeMemBlock = NULL;
//     slave_pool[_myid].self1 = NULL;

//     slave_pool[_myid].FreeMemBlock = slave_mempool_allocblock(slave_pool[_myid]);
//     //    void *s=memset(((char *)pool.MemBlock+sizeof(struct Unit)),0, pool.UnitSize);
//     slave_pool[_myid].EndBlock =
//         (void *)((char *)(slave_pool[_myid].FreeMemBlock->data) + UNITSIZE);
       
//     slave_pool[_myid].self1 = (void *)(slave_pool[_myid].FreeMemBlock->data);
//     struct block *pCurUnit = slave_pool[_myid].FreeMemBlock;
//     slave_pool[_myid].FreeMemBlock = slave_pool[_myid].FreeMemBlock->next;
//     pCurUnit->next = slave_pool[_myid].AllocatedMemBlock;
//     slave_pool[_myid].AllocatedMemBlock = pCurUnit;
// }

void slave_InitPool()  // use _MYID?
{
    // alog_debug("InitPool");
    slave_pool_ldm.EndBlock = slave_pool[_MYID].EndBlock;
    slave_pool_ldm.AllocatedMemBlock = slave_pool[_MYID].AllocatedMemBlock;
    slave_pool_ldm.FreeMemBlock = slave_pool[_MYID].FreeMemBlock;
    slave_pool_ldm.self1 = slave_pool[_MYID].self1;

    // slave_pool_ldm.FreeMemBlock = slave_mempool_allocblock(slave_pool_ldm);
    // printf("_MYID: %d\n", _MYID);
    // slave_pool_ldm.FreeMemBlock = slave_pool[_MYID].FreeMemBlock;

    // //    void *s=memset(((char *)pool.MemBlock+sizeof(struct Unit)),0, pool.UnitSize);
    // slave_pool_ldm.EndBlock =
    //     (void *)((char *)(slave_pool_ldm.FreeMemBlock->data) + UNITSIZE);
       
    // slave_pool_ldm.self1 = (void *)(slave_pool_ldm.FreeMemBlock->data);
    // struct block *pCurUnit = slave_pool_ldm.FreeMemBlock;
    // slave_pool_ldm.FreeMemBlock = slave_pool_ldm.FreeMemBlock->next;
    // pCurUnit->next = slave_pool_ldm.AllocatedMemBlock;
    // slave_pool_ldm.AllocatedMemBlock = pCurUnit;
    // printf("FreeMemBlock\n");

}

void slave_ReInitial(int _myid)
{
    // alog_debug("ReInitialPool");
    while (slave_pool[_myid].AllocatedMemBlock != NULL) {
        struct block *pCurUnit = slave_pool[_myid].AllocatedMemBlock;
        // void* s=memset(((char *)pool.AllocatedMemBlock+sizeof(struct Unit)),0, pool.UnitSize);
        slave_pool[_myid].AllocatedMemBlock = slave_pool[_myid].AllocatedMemBlock->next;
        pCurUnit->next = slave_pool[_myid].FreeMemBlock;
        slave_pool[_myid].FreeMemBlock = pCurUnit;
    }
    slave_pool[_myid].self1 = (void *)(slave_pool[_myid].FreeMemBlock->data);
    slave_pool[_myid].EndBlock =
        (void *)((char *)(slave_pool[_myid].FreeMemBlock->data) + UNITSIZE);
    struct block *pCurUnit = slave_pool[_myid].FreeMemBlock;
    slave_pool[_myid].FreeMemBlock = slave_pool[_myid].FreeMemBlock->next;
    pCurUnit->next = slave_pool[_myid].AllocatedMemBlock;
    slave_pool[_myid].AllocatedMemBlock = pCurUnit;
}

void slave_FreePool(int _myid)
{
    // alog_debug("FreePool");
    while (slave_pool[_myid].FreeMemBlock != NULL) {
        struct block *pCurUnit = slave_pool[_myid].FreeMemBlock;
        slave_pool[_myid].FreeMemBlock = slave_pool[_myid].FreeMemBlock->next;
#ifdef TARG_SW5
        free(pCurUnit->data);
        free(pCurUnit);
#elif TARG_SW9
        libc_uncached_aligned_free(pCurUnit->data);
        libc_uncached_aligned_free(pCurUnit);
#else
        printf("mempool hasn't free\n");
#endif
    }
}
void slave_getEndBlock(int myid){
    printf("slave_getEndBlock%d,self%d\n",(char *)slave_pool[myid].EndBlock);
}
// void *slave_acemesh_myalloc_aligned_16(int datasize, int myid)
// {
// //printf("slave_myalloc_16\n");
//         if ((long long)slave_pool[myid].self1 % 16 > 0)
//         slave_pool[myid].self1 = (void *)((char *)slave_pool[myid].self1 +
//                                           (16 - (long long)slave_pool[myid].self1 % 16));
// // printf("EndBlock%d,self%d\n",(char *)slave_pool[myid].EndBlock,(char *)slave_pool[myid].self1);    

// // printf("myid%d,size%d,datasize%d\n",myid,((char *)slave_pool[myid].EndBlock - (char *)slave_pool[myid].self1),datasize);    
// if (((char *)slave_pool[myid].EndBlock - (char *)slave_pool[myid].self1) < datasize) {
// //printf("need remlloc\n");
//         if (slave_pool[myid].FreeMemBlock == NULL) {
//             slave_pool[myid].FreeMemBlock = slave_mempool_allocblock(slave_pool[myid]);
//         }
//         struct block *pCurUnit = slave_pool[myid].FreeMemBlock;
//         slave_pool[myid].FreeMemBlock = slave_pool[myid].FreeMemBlock->next;
//         pCurUnit->next = slave_pool[myid].AllocatedMemBlock;
//         slave_pool[myid].AllocatedMemBlock = pCurUnit;
//         slave_pool[myid].EndBlock = (void *)((char *)(pCurUnit->data) + UNITSIZE);
//         slave_pool[myid].self1 = (void *)(pCurUnit->data);
 
// }
// //printf("2\n");
//     void *self = (void *)slave_pool[myid].self1;
//     slave_pool[myid].self1 = (void *)((char *)slave_pool[myid].self1 + datasize);
// //printf("3\n");
//     return (void *)self;
// }

void *slave_acemesh_myalloc_aligned_16(int datasize, int myid)
{
    // slave_pool_ldm.self1 = slave_pool[myid].self1;
    // slave_pool_ldm.EndBlock = slave_pool[myid].EndBlock;
    // slave_pool_ldm.AllocatedMemBlock = slave_pool[myid].AllocatedMemBlock;
    // slave_pool_ldm.FreeMemBlock = slave_pool[myid].FreeMemBlock;
    // get_reply = 0;
    // athread_get(PE_MODE, &slave_pool[myid], &slave_pool_ldm, sizeof(struct MemPool), (void *)&get_reply, 0, 0, 0);
    // while(get_reply!=1);
    if ((long long)slave_pool_ldm.self1 % 16 > 0)
    slave_pool_ldm.self1 = (void *)((char *)slave_pool_ldm.self1 +
                                        (16 - (long long)slave_pool_ldm.self1 % 16));
    // printf("EndBlock%d,self%d\n",(char *)slave_pool_ldm.EndBlock,(char *)slave_pool_ldm.self1);    

    // printf("myid%d,size%d,datasize%d\n",myid,((char *)slave_pool_ldm.EndBlock - (char *)slave_pool_ldm.self1),datasize);    
    if (((char *)slave_pool_ldm.EndBlock - (char *)slave_pool_ldm.self1) < datasize) {  //0.2秒
    //printf("need remlloc\n");
        if (slave_pool_ldm.FreeMemBlock == NULL) {
            slave_pool_ldm.FreeMemBlock = slave_mempool_allocblock(slave_pool_ldm);
        }
        struct block *pCurUnit = slave_pool_ldm.FreeMemBlock;
        slave_pool_ldm.FreeMemBlock = slave_pool_ldm.FreeMemBlock->next;
        pCurUnit->next = slave_pool_ldm.AllocatedMemBlock;
        slave_pool_ldm.AllocatedMemBlock = pCurUnit;
        slave_pool_ldm.EndBlock = (void *)((char *)(pCurUnit->data) + UNITSIZE);
        slave_pool_ldm.self1 = (void *)(pCurUnit->data);
    }
    //printf("2\n");
    void *self = (void *)slave_pool_ldm.self1;
    // slave_pool[myid].self1 = (void *)((char *)self + datasize);
    slave_pool_ldm.self1 = (void *)((char *)self + datasize);
    //printf("3\n");
    return (void *)self;
}

void *slave_acemesh_myalloc_aligned_64(int datasize, int _myid)
{
    if ((long long)slave_pool[_myid].self1 % 64 > 0)
        slave_pool[_myid].self1 = (void *)((char *)slave_pool[_myid].self1 +
                                           (64 - (long long)slave_pool[_myid].self1 % 64));
    printf("myalloc_aligned_64\n");
    if (((char *)slave_pool[_myid].EndBlock - (char *)slave_pool[_myid].self1) < datasize) {
        if (slave_pool[_myid].FreeMemBlock == NULL) {
            slave_pool[_myid].FreeMemBlock = slave_mempool_allocblock(slave_pool[_myid]);
        }
        struct block *pCurUnit = slave_pool[_myid].FreeMemBlock;
        slave_pool[_myid].FreeMemBlock = slave_pool[_myid].FreeMemBlock->next;
        pCurUnit->next = slave_pool[_myid].AllocatedMemBlock;
        slave_pool[_myid].AllocatedMemBlock = pCurUnit;
        slave_pool[_myid].EndBlock = (void *)((char *)(pCurUnit->data) + UNITSIZE);
        slave_pool[_myid].self1 = (void *)(pCurUnit->data);

        printf("need_remalloc_memmery\n");
    }

    void *self = (void *)slave_pool[_myid].self1;
    slave_pool[_myid].self1 = (void *)((char *)slave_pool[_myid].self1 + datasize);
    return (void *)self;
}
#ifdef TARG_SW9
void *slave_my_malloc_aligned(int size)
{
    if (size <= 0) return NULL;
    //    printf("%d",size);
    //    fflush(stdout);
    void *self = libc_uncached_aligned_malloc(size);
    //    printf(",\t");
    //    fflush(stdout);
    return self;
}
void slave_my_free_aligned(void *self) { libc_uncached_aligned_free(self); }
#endif
